package com.sina.shop.manage.service.admin;


import com.sina.shop.core.exception.client.DataException;
import com.sina.shop.core.exception.server.ResourceExistsException;
import com.sina.shop.core.exception.server.UpdateException;
import com.sina.shop.domain.admin.Permission;
import com.sina.shop.manage.dao.admin.PermissionManageDao;
import com.sina.shop.service.ShopDataSourceService;
import com.sina.shop.util.Assert;
import com.sina.shop.util.CollectionUtils;
import com.sina.shop.util.ResultCode;
import com.sina.shop.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

import static com.sina.shop.service.ServiceConstant.SHOP_TX;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * 段浩杰   2017-11-03-14:25
 */
@Service("permissionManageService")
public class PermissionManageServiceImpl extends ShopDataSourceService implements PermissionManageService {

    @Qualifier("permissionManageDao")
    @Autowired
    private PermissionManageDao permissionManageDao;

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public Permission getPermissionByName(String name) {
        return permissionManageDao.getPermissionByName(name);
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public Permission getPermissionById(Long id) {
        return permissionManageDao.get(Permission.class, id);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Permission savePermission(Permission permission) throws UpdateException, DataException {

        boolean exists;
        exists = permissionManageDao.isExistsByUnique(Permission.class, "name", permission.getName());
        Assert.assertFalse(exists, ResourceExistsException.class, ResultCode.dataExists
                , "Permission[%s] exists", permission.getName());

        try {
            permissionManageDao.save(permission);
            permissionManageDao.flush();

            return permission;
        } catch (DataAccessException e) {
            LOG.error(" {} save Permission error.", Permission.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Permission updatePermission(Permission permission) throws UpdateException, DataException {

        Permission p = permissionManageDao.get(Permission.class, permission.getId());
        Assert.assertNotNull(p, "Permission[id=%s] not exists", permission.getId());

        try {
            updatePermissionFiled(permission, p);
            permissionManageDao.flush();

            return p;
        } catch (DataAccessException e) {
            LOG.error(" {} update Permission error.", Permission.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }

    }

    /**
     * 所需要更新的字段的转换
     *
     * @param oldPermission 前台传来的permission（瞬时态）
     * @param newPermission 从数据库中查询的permission（持久态）
     * @return newPermission   最后要变为的permission（执行完update后变为游离态）
     */
    public Permission updatePermissionFiled(Permission oldPermission, Permission newPermission) {

        if (oldPermission.getPermission() != null) {
            newPermission.setPermission(oldPermission.getPermission());
        }
        if (!StringUtils.isEmpty(oldPermission.getName())) {
            newPermission.setName(oldPermission.getName());
        }
        if (!CollectionUtils.isEmpty(oldPermission.getRoles())) {
            newPermission.setRoles(oldPermission.getRoles());
        }
        if (!CollectionUtils.isEmpty(oldPermission.getPermissions())) {
            newPermission.setPermissions(oldPermission.getPermissions());
        }
        if (!StringUtils.isEmpty(oldPermission.getType())) {
            newPermission.setType(oldPermission.getType());
        }
        if (oldPermission.getSort() != null) {
            newPermission.setSort(oldPermission.getSort());
        }
        if (!StringUtils.isEmpty(oldPermission.getPermCode())) {
            newPermission.setPermCode(oldPermission.getPermCode());
        }
        if (!StringUtils.isEmpty(oldPermission.getDescription())) {
            newPermission.setDescription(oldPermission.getDescription());
        }
        if (oldPermission.getUpdateTime() != null) {
            newPermission.setUpdateTime(oldPermission.getUpdateTime());
        }
        if (!StringUtils.isEmpty(oldPermission.getStatus())) {
            newPermission.setStatus(oldPermission.getStatus());
        }
        return newPermission;
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getPermissionList(Permission permission, Long[] count) {

        if (count != null && count.length > 0) {
            count[0] = permissionManageDao.getPermissionCount(permission);
        }

        return permissionManageDao.getPermissionList(permission);
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getPermissionIdAndNameList(Boolean hasAll) {
        return permissionManageDao.getPermissionIdAndNameList(hasAll);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public int deletePermission(Long id) throws UpdateException, DataException {
        Permission p = permissionManageDao.get(Permission.class, id);
        Assert.assertNotNull(p, "Permission[id=%s] not exists", p.getId());

        try {
            return permissionManageDao.deletePermission(id);
        } catch (DataAccessException e) {
            LOG.error(" {} delete Permission error.", Permission.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }
}
